package HtServer.meeting;

import HtServer.returnObject.ReturnObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;

//import org.apache.catalina.Session;
import tools.Configure;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


//@WebListener

@ServerEndpoint(value = "/MWS")
public class MeetingWebSocket implements ServletContextListener

{

    //    private static final Set<Session> sessions = new HashSet<Session>();
    private static final Set<Session> sessions =  Collections.synchronizedSet(new HashSet<Session>());
    private static Boolean ifopen = false;
    private static ScheduledExecutorService scheduler ;
//    WebSocketContainer container = ContainerProvider.getWebSocketContainer();

    public MeetingWebSocket() {
//        container.setDefaultMaxTextMessageBufferSize(6553500);
//        container.setDefaultMaxBinaryMessageBufferSize(6553600); // 64 KB
        System.out.println("构造函数");
    }


    @OnOpen
    public  void onOpen(Session session, EndpointConfig config) throws IOException {

        System.out.println("session 是否是null"+(session == null));

        String queryString = session.getQueryString();
        Map qs = parseQueryString(queryString);
        String isMobile = (String) qs.get("isMobile");

        synchronized (sessions) {
            if (isMobile != null && isMobile.equals("true")) {
                session.getUserProperties().put("isMobile", true);
            } else {
                session.getUserProperties().put("isMobile", false);
            }
            sessions.add(session);

        }
//        System.out.println(session.getMaxIdleTimeout());
//        session.setMaxIdleTimeout(10000); // 设置超时
        System.out.println("总数="+sessions.size());


    }
    @OnMessage
    public void onMessage(String message,Session session) throws IOException {
        try {

            System.out.println("onmessage" + (message==null?"null":message));
            synchronized (sessions){
                sendToAll(session,message);
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("56 行 onMessage：" + e.getMessage());
            System.err.println(e);
            System.err.println(e.getStackTrace());
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason){

        System.out.print(closeReason.getReasonPhrase());
        System.out.println("onClose");
        System.out.println("session 是否是null  :"+(session == null));
        synchronized (sessions) {
//            if (session != null)
//                sessions.remove(session);
        }
    }
    @OnError
    public void onError(Session session, Throwable throwable){


//        System.err.println("error");
//        System.err.println("throwable.getMessage()="+throwable.getMessage());
//
//        System.out.println("throwable.getcause = "+throwable.getCause());
//        System.out.println("剩余连接="+sessions.size());


//        System.err.println("Error occurred in session: {}, Error: {}"+(session != null ? session.getId() : "Unknown")+throwable.getMessage());
//        System.err.println("Exception stack trace: "+throwable);
        // 处理错误并关闭连接
        synchronized(sessions) {

            if (session != null && session.isOpen()) {
                try {
                    session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Unexpected error"));
                } catch (IOException e) {
                    System.err.println("Error closing session: " + e);
                }
            }
        }
//        throwable.printStackTrace();
    }

    protected   void sendToAll(Session session,String message) throws Exception {
        synchronized (sessions)
        {
            String str = JSON.toJSONString(message);


            JSONObject strjson = JSON.parseObject(message);
            //like
            if (strjson.getString("type").equals("1")) {
                MeetingItem mi = MeetingItems.getInstance().getCurrentItem();
                mi.addLike();
                for (Session session_temp : sessions) {

                    if(session_temp.isOpen())
                    {
                        ReturnObject rto = new ReturnObject();
                        JSONObject jo = new JSONObject();
                        jo.put("type", "1");
                        jo.put("meetingitem", mi);
                        rto.setMsg("成功");
                        rto.setType(ReturnObject.SUCCESS);
                        rto.setJson(jo);
                        session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));


                        mi.saveMeetingItem2Redis();

                    }


                }
            }

            //unlike
            else if (strjson.getString("type").equals("2"))
            {
                for (Session session_temp : sessions) {

                    MeetingItem mi = MeetingItems.getInstance().getCurrentItem();
                    mi.addUnLike();

                    if(session_temp.isOpen())
                    {
                        ReturnObject rto = new ReturnObject();
                        JSONObject jo = new JSONObject();
                        jo.put("type", "2");
                        jo.put("meetingitem", JSON.toJSONString(mi));
                        rto.setMsg("成功");
                        rto.setType(ReturnObject.SUCCESS);
                        rto.setJson(jo);
                        session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
                    }
                }
            }

            //get next mi
            else if(strjson.getString("type").equals("3"))
            {
                MeetingItem mi = MeetingItems.getInstance().getNextItem();
                MeetingItem nextmi = MeetingItems.getInstance().getNextItemNotGo();
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp)
                            {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "3");

                                //手机端不发送人物头像和内容，剩下流量
                                if (session_temp.getUserProperties().get("isMobile").equals(true))
                                {
                                    MeetingItem mi_temp = new MeetingItem();
                                  //  mi_temp = mi;
                                    mi_temp.setContents("");
                                    mi_temp.setImage("");
                                    mi_temp.setId(mi.getId());
                                    mi_temp.setDept(mi.getDept());
                                    mi_temp.setGroupid(mi.getGroupid());
                                    mi_temp.setGroupname(mi.getGroupname());
                                    mi_temp.setOrder(mi.getOrder());
                                    mi_temp.setLike(mi.getLike());
                                    mi_temp.setName(mi.getName());
                                    mi_temp.setUnlike(mi.getUnlike());
                                    jo.put("meetingitem", mi_temp);
//                                    jo.put("nextmi", nextmi);
                                }
                                else
                                {
                                    jo.put("meetingitem", mi);
                                    jo.put("nextmi", nextmi);
                                }

                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.err.println("发送错误：type 3" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }
            }
            //get pre mi
            else if(strjson.getString("type").equals("4"))
            {
                MeetingItem mi = MeetingItems.getInstance().getPreItem();
                MeetingItem nextmi = MeetingItems.getInstance().getNextItemNotGo();
                for (Session session_temp : sessions)
                {
                    if (session_temp.isOpen())
                        try {
//                            synchronized (session_temp)
                            {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "4");
                                jo.put("meetingitem", mi);
                                jo.put("nextmi", nextmi);
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
//                                System.out.println(rto.getJson().toJSONString().getBytes().length);

                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));


                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            System.err.println("发送错误：type 4" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }
            }

            //get current mi 广播到所有
            else if(strjson.getString("type").equals("7"))
            {
                MeetingItem mi = MeetingItems.getInstance().getCurrentItem();

                MeetingItem nextmi = MeetingItems.getInstance().getNextItemNotGo();
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp)
                            {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "7");
                                jo.put("meetingitem", mi);
                                jo.put("nextmi", nextmi);
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 7" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }
            }


            //只广播到自己
            else if(strjson.getString("type").equals("71"))
            {
                MeetingItem mi = MeetingItems.getInstance().getCurrentItem();

                MeetingItem nextmi = MeetingItems.getInstance().getNextItemNotGo();

                synchronized (session)
                {
                    ReturnObject rto = new ReturnObject();
                    JSONObject jo = new JSONObject();
                    jo.put("type", "71");
                    jo.put("meetingitem", mi);
                    jo.put("nextmi", nextmi);
                    rto.setMsg("成功");
                    rto.setType(ReturnObject.SUCCESS);
                    rto.setJson(jo);
                    session.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                }


            }
            else if(strjson.getString("type").equals("5"))
            {
                autoSendItem();
            }
            else if(strjson.getString("type").equals("6"))
            {
                shutdown();
            }


            else if(strjson.getString("type").equals("10"))
            {
                int rollspeednum = strjson.getInteger("rollspeednum");
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp)
                            {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "10");
                                jo.put("rollspeednum", rollspeednum);
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 10" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }
            }
            //返回所有item
            else if(strjson.getString("type").equals("11")) {
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "11");
                                jo.put("meetingitems", MeetingItems.getInstance().getAllItems());
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 11" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }
            //返回指定人员
            else if(strjson.getString("type").equals("12")) {
                String id = strjson.getString("selected");
                MeetingItem mi =  MeetingItems.getInstance().getMeetingItem(id);
                if(mi!=null)
                {
                    for (Session session_temp : sessions) {
                        if (session_temp.isOpen())
                            try {
                                synchronized (session_temp) {
                                    ReturnObject rto = new ReturnObject();
                                    JSONObject jo = new JSONObject();
                                    jo.put("type", "12");
                                    jo.put("meetingitem", mi);
                                    rto.setMsg("成功");
                                    rto.setType(ReturnObject.SUCCESS);
                                    rto.setJson(jo);
                                    session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                                }
                            } catch (Exception e) {
                                System.out.println("发送错误：type 12" + e.getMessage());
                                System.err.println(e.getMessage());
                            }

                    }
                }
            }

            //设置唯一控制主机

            else if(strjson.getString("type").equals("20")) {

                {
                    for (Session session_temp : sessions) {
                        if (session_temp.isOpen())
                            try {
                                synchronized (session_temp) {
                                    //当前提交的session 就是主机
                                    if(session_temp.equals(session))
                                    {
                                        ReturnObject rto = new ReturnObject();
                                        JSONObject jo = new JSONObject();
                                        jo.put("type", "20");
                                        jo.put("isMainHost", true);
                                        rto.setMsg("成功");
                                        rto.setType(ReturnObject.SUCCESS);
                                        rto.setJson(jo);
                                        session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
                                    }
                                    else {
                                        ReturnObject rto = new ReturnObject();
                                        JSONObject jo = new JSONObject();
                                        jo.put("type", "20");
                                        jo.put("isMainHost", false);
                                        rto.setMsg("成功");
                                        rto.setType(ReturnObject.SUCCESS);
                                        rto.setJson(jo);
                                        session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
                                    }
                                }
                            } catch (Exception e) {
                                System.out.println("发送错误：type 20" + e.getMessage());
                                System.err.println(e.getMessage());
                            }
                    }
                }


            }

            //全屏
            else if(strjson.getString("type").equals("100")) {

                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "100");

                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 100" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }

            }
            //退出全屏
            else if(strjson.getString("type").equals("101")) {

                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "101");

                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 101" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }

            }

            else if(strjson.getString("type").equals("200"))
            {
//                let backgroupimageid = MeetingReturnObject.json.backgroupimageid;


                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "200");
                                String backgroupimageid = strjson.getString("backgroupid");
                                backgroupimageid = Configure.getInstance().getProperties().getProperty(backgroupimageid);
//                                System.out.println("backgroupimageid="+backgroupimageid);
                                jo.put("backgroupimageid", backgroupimageid);
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 200" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }

            else if(strjson.getString("type").equals("300"))
            {
//                let backgroupimageid = MeetingReturnObject.json.backgroupimageid;

                MeetingItem mi =  MeetingItems.getInstance().getFirstItem();
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "300");

                                jo.put("meetingitem", mi);


                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 300" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }

            else if(strjson.getString("type").equals("301"))
            {
//                let backgroupimageid = MeetingReturnObject.json.backgroupimageid;


                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "301");

                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 301" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }
            //改变字体大小
            else if(strjson.getString("type").equals("400"))
            {
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "400");
                                jo.put("fontsize", strjson.getString("fontsize"));
                                rto.setMsg("成功1");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 400" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }

            //改变颜色
            else if(strjson.getString("type").equals("401"))
            {
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "401");
                                jo.put("fontcolor", strjson.getString("colorselected"));
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 401" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }
            //设置总体播放时间，单位秒
            else if(strjson.getString("type").equals("500"))
            {
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {
                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "500");
                                int playtime = strjson.getInteger("playTime");
                                int rollspeed = MeetingItems.getInstance().getMeetingItemTimeFromRedis(playtime,2);

                                jo.put("rollspeed",rollspeed);


                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));

                            }
                        } catch (Exception e) {
                            System.out.println("发送错误：type 500" + e.getMessage());
                            System.err.println(e.getMessage());
                        }

                }
            }
            //设置总体播放时间，单位秒
            else if(strjson.getString("type").equals("501"))
            {

            }

            //显示结果
            else if(strjson.getString("type").equals("900"))
            {
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp)
                            {

                                System.out.println(session_temp.getUserProperties().get("isMobile"));
                                //手机端不发送人物头像和内容，剩下流量
                                if (session_temp.getUserProperties().get("isMobile").equals(true))
                                {

                                }
                                else
                                {
                                    ReturnObject rto = new ReturnObject();
                                    JSONObject jo = new JSONObject();
                                    jo.put("type", "900");
                                    rto.setMsg("成功");
                                    rto.setType(ReturnObject.SUCCESS);
                                    rto.setJson(jo);
                                    session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
                                }



                            }
                        } catch (Exception e) {
                            System.err.println("发送错误：type 3" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }


            }
            //重新加载所有数据
            else if(strjson.getString("type").equals("999"))
            {
                MeetingItems.getInstance().getMeetingItemFromRedis();
                MeetingItems.getInstance().sort();


            }



        }
    }
    protected void shutdown() {
        scheduler.shutdown();
        ifopen = false;
    }

    public void autoSendItem()
    {
        System.out.println("autoSendItem");
        synchronized (ifopen) {
            if (ifopen)
                return;
            ifopen = true;
            // 在启动时，调度一个定时任务，每隔一段时间向客户端发送消息
            scheduler = Executors.newScheduledThreadPool(1);
            scheduler.scheduleAtFixedRate(() -> {


                MeetingItem mi = MeetingItems.getInstance().getNextItem();
                for (Session session_temp : sessions) {
                    if (session_temp.isOpen())
                        try {
                            synchronized (session_temp) {

                                ReturnObject rto = new ReturnObject();
                                JSONObject jo = new JSONObject();
                                jo.put("type", "5");
                                jo.put("meetingitem", mi);
                                rto.setMsg("成功");
                                rto.setType(ReturnObject.SUCCESS);
                                rto.setJson(jo);
                                session_temp.getBasicRemote().sendText(JSON.toJSONString(rto));
//                                session_temp.getBasicRemote().sendText(JSON.toJSONString(mi));
                            }
                        } catch (Exception e) {
                            System.err.println("发送错误：auto send item" + e.getMessage());
                            System.err.println(e.getMessage());
                        }
                }
//            try {
//               System.out.println("auto send.");
//            }
//            catch (Exception e) {
//                e.printStackTrace();
//            }
            }, 0, 10, TimeUnit.SECONDS); //
        }

    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContextListener.super.contextInitialized(sce);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
        if (scheduler != null) {
            scheduler.shutdown();
        }
        sessions.clear();
    }


    private Map<String, String> parseQueryString(String queryString) {
        Map<String, String> queryParameters = new HashMap<>();
        if (queryString == null || queryString.isEmpty()) {
            return queryParameters;
        }

        String[] pairs = queryString.split("&");
        for (String pair : pairs) {
            int idx = pair.indexOf("=");
            try {
                String key = URLDecoder.decode(pair.substring(0, idx), "UTF-8");
                String value = URLDecoder.decode(pair.substring(idx + 1), "UTF-8");
                queryParameters.put(key, value);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return queryParameters;
    }
}
